#include "UserController.h"
#include "DbMysql.h"

namespace XIAOO{
    //注册接口
    // @param usernmae string
    // @param password string
    Json::Value UserController::registe(Json::Value root){
        std::string username, password;
        username = root["data"]["username"].asString();
        password = root["data"]["password"].asString();

        if(username == "" || password == ""){
            return this->_echoJson(XIAOO::CODE_ACCOUNT_EXIST_ERROR, "plz input correct account and password");
        }
        //判断是否存在
        XIAOO::DbMysql db;
        std::string querySql;
        Json::Value queryData;
        querySql = "select * from h_user where username='" + username + "' limit 1";
        int res = db.query(querySql, &queryData);
        if(res){
            return this->_echoJson(XIAOO::CODE_DB_QUERY_ERROR, "query error");
        }else{
            if(queryData.size() > 0){
                return this->_echoJson(XIAOO::CODE_ACCOUNT_EXIST_ERROR, "account exist");
            }
        }
        //入库
        struct timeval tv;
        gettimeofday(&tv, NULL);
        std::string insertSql = "insert into h_user (`username`,`password`,`created_at`) values ('" + username + "','"+password+"', '"+std::to_string(tv.tv_sec)+"')";
        int lastInsertId = 0;
        if(db.insert(insertSql, &lastInsertId)){
            return this->_echoJson(XIAOO::CODE_DB_INSERT_ERROR, "insert error");
        }

        Json::Value data;
        data["uid"] = lastInsertId;
        //返回
        return this->_echoJson(XIAOO::CODE_SUCCESS, "registe success", data);
    }

    // 登陆接口
    // @param username string 
    // @param password string
    Json::Value UserController::login(Json::Value root, int sockfd){
        Json::Value data;
        data = root["data"];

        int uid;
        std::string password;
        uid = root["data"]["uid"].asInt();
        password = root["data"]["password"].asString();

        if(uid <= 0 || password == ""){
            return this->_echoJson(XIAOO::CODE_PASSWORD_ERROR, "empty param");
        }

        //查库
        XIAOO::DbMysql db;
        Json::Value queryData;
        std::string querySql = "select * from h_user where id=" + std::to_string(uid) +" and password="""+password+""" limit 1";
        int res = db.queryOne(querySql, &queryData);
        if(res){
            return this->_echoJson(XIAOO::CODE_DB_QUERY_ERROR, "query error");
        }
        
        
        if(!queryData.isNull()){
            if(!this->addMapForUidAndSockfd(queryData, sockfd)){
                return this->_echoJson(XIAOO::CODE_PASSWORD_ERROR, "the uid has been logined");
            }
            return this->_echoJson(XIAOO::CODE_SUCCESS, "success", queryData);
        }else{
            //账号不存在或密码错误
            return this->_echoJson(XIAOO::CODE_PASSWORD_ERROR, "no such account or password error");
        }
    }

    //获取个人信息
    Json::Value UserController::getUserInfo(Json::Value root){
        XIAOO::userEntity user;
        if(this->_checkLogin(root, &user) == false){
            return this->_echoJson(XIAOO::CODE_UNLOGIN_ERROR, "unlogin or error account");
        }

        int uid = root["data"]["uid"].asInt();

        //查询用户信息
        XIAOO::DbMysql db;
        Json::Value queryData;
        std::string querySql = "select * from h_user where id=" + std::to_string(uid) +" limit 1";
        int res = db.queryOne(querySql, &queryData);
        if(res){
            return this->_echoJson(XIAOO::CODE_DB_QUERY_ERROR, "query error");
        }
        
        if(queryData.size() > 0){
            return this->_echoJson(XIAOO::CODE_SUCCESS, "success", queryData);
        }else{
            //账号不存在
            return this->_echoJson(XIAOO::CODE_PASSWORD_ERROR, "query error");
        }
    }

    // 添加好友
    // @param uid  int 我的uid
    // @param beuid string 被添加的好友uid
    Json::Value UserController::addFriend(Json::Value root){
        XIAOO::userEntity user;
        if(this->_checkLogin(root, &user) == false){
            return this->_echoJson(XIAOO::CODE_UNLOGIN_ERROR, "unlogin or error account");
        }

        int uid = root["data"]["uid"].asInt();
        int beuid = root["data"]["beuid"].asInt();

        //判断beuid是否存在
        XIAOO::DbMysql db;
        Json::Value queryData;
        std::string querySql = "select * from h_user where id=" + std::to_string(beuid) +" and status=1 limit 1";
        if(db.query(querySql, &queryData)){
            return this->_echoJson(XIAOO::CODE_DB_QUERY_ERROR, "query error");
        }
        
        if(queryData.size() <= 0){
            return this->_echoJson(XIAOO::CODE_ACCOUNT_NOT_EXIST_ERROR, "no such account");
        }

        //判断是否已经有该好友了
        Json::Value queryDataFriend;
        std::string queryFriendSql = "select * from h_user_relation where uid="+std::to_string(uid)+" and beuid=" + std::to_string(beuid) +" limit 1";
        if(db.query(queryFriendSql, &queryDataFriend)){
            return this->_echoJson(XIAOO::CODE_DB_QUERY_ERROR, "query error");
        }
        
        if(queryDataFriend.size() > 0){
            return this->_echoJson(XIAOO::CODE_EXIST_FRIEND_ERROR, "exist friend");
        }

        //添加好友入库
        struct timeval tv;
        gettimeofday(&tv, NULL);
        std::string insertSql = "insert into h_user_relation (`uid`,`beuid`,`is_active`,`created_at`) values (" + std::to_string(uid) + ","+std::to_string(beuid)+",1, '"+std::to_string(tv.tv_sec)+"')";
        std::string insertSqlBeuid = "insert into h_user_relation (`uid`,`beuid`,`created_at`) values (" + std::to_string(beuid) + ","+std::to_string(uid)+", '"+std::to_string(tv.tv_sec)+"')";
        int lastInsertId = 0;
        int lastInsertId2 = 0;
        if(db.insert(insertSql, &lastInsertId) || db.insert(insertSqlBeuid, &lastInsertId2)){
            return this->_echoJson(XIAOO::CODE_DB_INSERT_ERROR, "insert error");
        }

        //返回
        return this->_echoJson(XIAOO::CODE_SUCCESS, "success");
    }

    // 好友列表
    // @param uid 
    Json::Value UserController::friendList(Json::Value root){
        XIAOO::userEntity user;
        if(this->_checkLogin(root, &user) == false){
            return this->_echoJson(XIAOO::CODE_UNLOGIN_ERROR, "unlogin or error account");
        }

        int uid = root["data"]["uid"].asInt();
        //查询好友列表v2
        XIAOO::DbMysql db;
        std::string querySql1;
        Json::Value queryData1;
        querySql1 = "select * from h_user_relation where uid=" + std::to_string(uid) + " limit 10";
        if (db.query(querySql1, &queryData1)){
            return this->_echoJson(XIAOO::CODE_DB_QUERY_ERROR, "query error");
        }
        
        std::string beuids = "";
        for (int i = 0; i < queryData1.size(); i++){
            if(i == 0){
                beuids = queryData1[i]["beuid"].asString();
            }else{
                beuids += "," + queryData1[i]["beuid"].asString();
            }
        }

        std::string querySql2;
        Json::Value queryData2;
        querySql2 = "select * from h_user where id in (" + beuids + ")";
        if (db.query(querySql2, &queryData2)){
            return this->_echoJson(XIAOO::CODE_DB_QUERY_ERROR, "query error2");
        }
        
        return this->_echoJson(XIAOO::CODE_SUCCESS, "success", queryData2);

        //查询好友列表v1
        // XIAOO::DbMysql db;
        // std::string querySql;
        // Json::Value queryData;
        // querySql = "select * from h_user where id in (select beuid from h_user_relation where uid=" + std::to_string(uid) + " limit 10) limit 10";
        // int res = db.query(querySql, &queryData);
        // if(res){
        //     return this->_echoJson(XIAOO::CODE_DB_QUERY_ERROR, "query error");
        // }else{
        //     return this->_echoJson(XIAOO::CODE_SUCCESS, "success", queryData);
        // }
    }

    Json::Value UserController::chat(Json::Value root, int sockfd){
        XIAOO::userEntity user;
        if(this->_checkLogin(root, &user) == false){
            return this->_echoJson(XIAOO::CODE_UNLOGIN_ERROR, "unlogin or error account");
        }

        // int uid = root["data"]["uid"].asInt();
        int beuid = root["data"]["beuid"].asInt();
        root["data"]["from_username"] = user.username;
        // std::string msg = root["data"]["msg"].asString();
        root["route"] = this->recvChatCallback;

        Json::StreamWriterBuilder builder;
        std::string postData = Json::writeString(builder, root);

        if(XIAOO::uidSockfdMap.count(beuid)){
            int beuidSockfd = XIAOO::uidSockfdMap[beuid];
            int writeBufferSize = postData.length() + 1;

            if(sockfd == beuidSockfd){
                return this->_echoJson(XIAOO::CODE_CHAT_ERROR, "can't chat with yourself");
            }

            int re = write(beuidSockfd, (char*)postData.c_str(), writeBufferSize);
            if(re == -1){
                return this->_echoJson(XIAOO::CODE_CHAT_ERROR, "send error");
            }

            return this->_echoJson(XIAOO::CODE_SUCCESS, "success");
        }else{
            return this->_echoJson(XIAOO::CODE_CHAT_ERROR, "friend off line");
        }
    }

    bool UserController::addMapForUidAndSockfd(Json::Value returnRoot, int sockfd){
        int uid = std::stoi(returnRoot["id"].asString());
        if(uid <= 0){
            return false;
        }

        // 判断该uid是否已经被登录了
        if(XIAOO::uidSockfdMap.count(uid)){
            std::cout << "【该账号已经被登录过了】" << std::endl;
            return false;
        }

        XIAOO::uidSockfdMap[uid] = sockfd;

        std::cout << "【玩家上线，最新uidSockfdMap begin】" << std::endl;
        std::cout << "【uid=>sock fd】" << std::endl;
        std::map<int, int>::const_iterator map_it = XIAOO::uidSockfdMap.begin();
        while(map_it != XIAOO::uidSockfdMap.end()){
            std::cout << map_it->first << "->" << (*map_it).second << std::endl;
            map_it++;
        }
        std::cout << "【玩家上线，最新uidSockfdMap end】" << std::endl;

        return true;
    }

    // 玩家下线
    // 1、剔除sockfd的字符集，这个在底层servernet已经做了
    // 2、剔除uidSockfdMap
    void UserController::offLine(int sockfd){
        std::map<int, int>::const_iterator map_it = XIAOO::uidSockfdMap.begin();
        std::cout << "【玩家下线，剔除uidSockfdMap begin】" << std::endl;
        printf("sockfd=%d\n", sockfd);
        printf("uid=>sock fd\n");
        while (map_it != XIAOO::uidSockfdMap.end())
        {
            std::cout << map_it->first << "->" << (*map_it).second << std::endl;
            if((*map_it).second == sockfd){
                printf("剔除uidSockfdMap的sock fd=%d\n", sockfd);
                XIAOO::uidSockfdMap.erase(map_it->first);
                break;
            }
            map_it++;
        }
        std::cout << "【玩家下线，剔除uidSockfdMap end】" << std::endl;
    }

    bool UserController::_checkLogin(Json::Value root, XIAOO::userEntity* user){
        int uid = root["data"]["uid"].asInt();
        XIAOO::DbMysql db;
        Json::Value queryData;
        std::string querySql = "select * from h_user where id=" + std::to_string(uid) +" and status=1 limit 1";
        if(db.query(querySql, &queryData)){
            return false;
        }

        if(queryData.size() <= 0){
            return false;
        }

        user->id = std::stoi(queryData[0]["id"].asString());
        user->age = std::stoi(queryData[0]["age"].asString());
        user->sex = std::stoi(queryData[0]["sex"].asString());
        user->created_at = std::stoi(queryData[0]["created_at"].asString());
        user->status = std::stoi(queryData[0]["status"].asString());

        user->username = queryData[0]["username"].asString();
        user->password = queryData[0]["password"].asString();

        return true;
    }

    Json::Value UserController::_echoJson(int code, std::string msg, Json::Value data){
        Json::Value re;
        re["code"] = code;
        re["msg"] = msg;
        re["data"] = data;

        return re;
    }

    UserController::UserController(){
        
    }

    UserController::~UserController(){
        // std::map<int, int>::const_iterator map_it = XIAOO::uidSockfdMap.begin();

        // printf("【服务器下线，剔除所有玩家 begin】\n");
        // printf("uid=>sock fd\n");
        // while (map_it != XIAOO::uidSockfdMap.end())
        // {
        //     std::cout << map_it->first << "->" << (*map_it).second << std::endl;
        //     map_it++;
        // }
        // printf("【服务器下线，剔除所有玩家 end】\n");
    }
}